package com.shop.zookeeper.distributeLock;

import org.I0Itec.zkclient.ZkClient;

import java.util.concurrent.CountDownLatch;

/**
 * @author Song Yinghui
 * @date 2019/12/6
 * @Version 1.0
 * <p>
 * 基于zookeeper 分布式锁
 */
public class ZkDistributeLock {

    private static final String lock_path = "/distribute_lock";

    private ZkClient zkClient;

    CountDownLatch countDownLatch;

    public ZkDistributeLock() {
        init();
    }

    private void init() {
        synchronized (ZkDistributeLock.class) {
            if (zkClient == null) {
                zkClient = new ZkClient("120.27.243.49:2181");
            }
            if (countDownLatch == null) {
                countDownLatch = new CountDownLatch(1);
            }
        }
    }

    public Boolean tryLock() {
        try {
            zkClient.createEphemeral(lock_path, lock_path);
            return true;
        } catch (Exception ex) {
            try {
                System.out.println(Thread.currentThread().getName()+"获取锁失败，线程暂时被挂起");
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return false;
        }
    }

    public void releaseLock() {
        System.out.println(Thread.currentThread().getName() + "释放锁");
        countDownLatch.countDown();
    }


    public static void main(String[] args) {

        ZkDistributeLock lock = new ZkDistributeLock();

        new Thread(() -> {
            System.out.println(String.format("线程1%s获取到锁", Thread.currentThread().getName()));
            try {
                Thread.sleep(3 * 1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.releaseLock();
        }).start();

        new Thread(() -> {
            lock.tryLock();
            System.out.println(String.format("线程2%s获取到锁", Thread.currentThread().getName()));
            try {
                Thread.sleep(3 * 1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.releaseLock();
        }).start();

        new Thread(() -> {
            lock.tryLock();
            System.out.println(String.format("线程3%s获取到锁", Thread.currentThread().getName()));
            try {
                Thread.sleep(3 * 1000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.releaseLock();
        }).start();
    }
}
